#pragma once 
#include<signal.h>
#include"connection.hpp"
#include"acceptor.hpp"
#include"LoopThread.hpp"


class TcpServer
{
private:
    /*为新连接构建一个Connection进行管理*/
    void NewConnection(int fd){
        _conn_id++;
        // PtrConnection conn(new Connection(&loop,conn_id,fd));
        // next_loop=(next_loop+1)%2;
        // PtrConnection conn(new Connection(threads[next_loop].GetLoop(),conn_id,fd));
        PtrConnection conn(new Connection(_pool.NextLoop(),_conn_id,fd));
        
        conn->SetConnectedCallback(_connected_callback);
        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetAnyEventCallback(_event_callback);
        conn->SetSrvClosedCallback(std::bind(&TcpServer::RemoveConnection,this,std::placeholders::_1));
        if(_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout);//启动非活跃超时销毁功能
        conn->Establish();//就绪初始化

        _conns.insert(std::make_pair(_conn_id,conn));
        DLOG("NEW--------------");
    }
    
    void RunAfterInLoop(const Functor& task,int delay){
        _timer_task_id++;
        _baseloop.TimerAdd(_timer_task_id,delay,task);
    }
    void RemoveConnectionInLoop(const PtrConnection&conn){
        int id=conn->Id();
        auto it=_conns.find(id);
        if(it!=_conns.end())
            _conns.erase(id);
    }
public:
    TcpServer(int port):_port(port),_conn_id(0),_timer_task_id(0),
    _enable_inactive_release(false),_acceptor(&_baseloop,_port),_pool(&_baseloop)
    {
        // _pool.Create();//创建线程池当中的从属线程//经测试，不能在构造函数来创建线程，因为此时的线程数为0，还没设置呢
        _acceptor.SetAccept(std::bind(&TcpServer::NewConnection,this,std::placeholders::_1));
        _acceptor.Listen();//将监听套接字挂到baseloop上开始监控事件
    }
    /*设置线程数量*/
    void SetThreadCount(int count){_pool.SetThreadCount(count);}
    /*设置是否启动非活跃超时销毁*/
    void EnableInactiveRelease(int timeout){_timeout=timeout;_enable_inactive_release=true;}
    /*提供添加定时任务接口*/
    void RunAfter(const Functor& task,int delay){
        _baseloop.RunLoop(std::bind(&TcpServer::RunAfterInLoop,this,task,delay));
    }
    /*给连接设置回调*/
    void SetConnectedCallback(const ConnectedCallback&cb){_connected_callback=cb;}
    void SetMessageCallback(const MessageCallback&cb){_message_callback=cb;}
    void SetClosedCallback(const ClosedCallback&cb){_closed_callback=cb;}
    void SetAnyEventCallback(const AnyEventCallback&cb){_event_callback=cb;}

    void Start(){
        _pool.Create();
        _baseloop.Start();
    }

    /*从管理Connection的_conns中移除连接信息---如果不从哈希中移除，就会一直保存着*/
    void RemoveConnection(const PtrConnection&conn){
        _baseloop.RunLoop(std::bind(&TcpServer::RemoveConnectionInLoop,this,conn));
    }

private:
    int _port;//服务器所许哟啊监听的端口
    uint64_t _conn_id;//自动增长的连接ID
    uint64_t _timer_task_id;//定时任务的id
    int _timeout;//非活跃连接的统计事件---多长时间无通信就是非活跃连接
    bool _enable_inactive_release;//是否启动了非活跃连接超时销毁的判断标志

    EventLoop _baseloop;//主线程的EventLoop对象，负责监听事件的处理
    Acceptor _acceptor;//监听套接字的管理对象
    LoopThreadPool _pool;//这是从属EventLoop线程池
    std::unordered_map<uint64_t,PtrConnection> _conns;//保存管理所有连接对应的shared_ptr对象
    //连接要设置的回调函数
    //阶段回调函数管理--提供给外界，来进行连接的某种操作的
    //这四个回调函数，是让服务器模块使用者来设置的
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
};
/*当连接断开的时候，如果我们还继续进行数据的发送，进行send的话，send就会触发一个异常，这个异常就会导致程序的退出*/
/*不想让他退出，忽略一下这个信号*/
class NetWork
{
public:
    NetWork(){
        DLOG("SIGPIPE INIT");
        signal(SIGPIPE,SIG_IGN);
    }
};
static NetWork nw;